home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.12 Dec 91 / Transfer Menu Code / Transfer Menu.p < prev    next >
Encoding:
Text File  |  1988-12-28  |  8.4 KB  |  321 lines  |  [TEXT/MPS ]

  1. (*******************************************************************
  2.     
  3.     Transfer Menu.p
  4.     
  5.     MDEF for dynamic Transfer menu demo.
  6.     
  7.     (c) 1988, by Clifford Story & Attic Software
  8.     
  9. *******************************************************************)
  10.     
  11. unit Transfermenu;
  12.     
  13. (******************************************************************)
  14.     
  15. interface
  16.     
  17. (******************************************************************)
  18.     
  19.     uses memtypes, quickdraw, osintf, toolintf, Common;
  20.     
  21. (******************************************************************)
  22.     
  23.     procedure menudef(message : integer; themenu : MenuHandle;
  24.                     var menurect : Rect; hitpoint : Point;
  25.                     var whichitem : integer);
  26.     
  27. (******************************************************************)
  28.     
  29. implementation
  30.     
  31. (******************************************************************)
  32.     
  33.     type
  34.         
  35.         QDrecord                =    record
  36.             randSeed            :    long;
  37.             screenBits        :    BitMap;
  38.             arrow                :    Cursor;
  39.             dkGray            :    Pattern;
  40.             ltGray            :    Pattern;
  41.             gray                :    Pattern;
  42.             black                :    Pattern;
  43.             white                :    Pattern;
  44.             thePort            :    GrafPtr;
  45.         end;
  46.         QDpointer            =    ^QDrecord;
  47.     
  48. (******************************************************************)
  49.     
  50.     procedure menudraw(themenu : MenuHandle; var menurect : Rect); forward;
  51.     procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
  52.                     hitpoint : Point; var whichitem : integer); forward;
  53.     procedure menusize(themenu : MenuHandle); forward;
  54.     
  55. (******************************************************************)
  56.     
  57.     {$R-}
  58.     {$SC+}
  59.     
  60. (*******************************************************************
  61.     
  62.     menudef
  63.     -------
  64.     
  65.     An MDEF is called to do three different things:  draw the menu,
  66.     hit-test a mouse location, or calculate the menu dimensions.
  67.     The “message” parameter determines which service is requested,
  68.     so the MDEF simply branches on “message” to specialized routines
  69.     that handle the specific functions.
  70.     
  71. *******************************************************************)
  72.     
  73.     procedure menudef(message : integer; themenu : MenuHandle;
  74.                     var menurect : Rect; hitpoint : Point;
  75.                     var whichitem : integer);
  76.         
  77.         begin
  78.             
  79.             case message of
  80.                 mDrawMsg        :    menudraw(themenu, menurect);
  81.                 mChooseMsg    :    menuchoose(themenu, menurect,
  82.                                                     hitpoint, whichitem);
  83.                 mSizeMsg        :    menusize(themenu);
  84.             end;
  85.         
  86.         end;
  87.     
  88. (******************************************************************
  89.     
  90.     qdglobals
  91.     ---------
  92.     
  93.     The qdglobals function returns a pointer to the quickdraw
  94.     globals.  This allows procedure definitions and desk accessories
  95.     to access the QD globals even though they can't call InitGraf.
  96.  
  97. ******************************************************************)
  98.  
  99.     function QDglobals : QDpointer;
  100.         
  101.         var
  102.             thepointer        :    longpointer;
  103.         
  104.         begin
  105.             
  106.             thepointer := longpointer(currenta5);
  107.             thepointer := longpointer(thepointer^);
  108.             QDglobals := QDpointer(long(thepointer^)
  109.                             - sizeof(QDrecord) + sizeof(GrafPtr));
  110.         
  111.         end;
  112.     
  113. (*******************************************************************
  114.     
  115.     menudraw
  116.     --------
  117.     
  118.     The “menudraw” routine draws the menu.
  119.     
  120.     The first item is the “Transfer...” command, the second is the
  121.     “Edit Transfer...” command, and the third is the separating Line
  122.     before the list of applications.  If there are no applications
  123.     in the list, then the list cannot be edited and so the second
  124.     item should be grayed out.
  125.     
  126.     The remaining items are found in the Transfer list that is kept
  127.     in the “TRNS” resource.  Each element of the list includes the
  128.     name of the application, which is drawn on the menu.
  129.     
  130. *******************************************************************)
  131.     
  132.     procedure menudraw(themenu: MenuHandle; var menurect: Rect);
  133.         
  134.         var
  135.             thehandle        :    thandle;
  136.             height            :    integer;
  137.             width                :    integer;
  138.             therect            :    Rect;
  139.             index                :    integer;
  140.             thestring        :    Str255;
  141.         
  142.         begin
  143.             
  144.             thehandle := thandle(GetResource('TRNS', 1001));
  145.             HLock(Handle(thehandle));
  146.             
  147.             height := menurect.top + 12;
  148.             width := menurect.left + 12;
  149.             
  150.             MoveTo(width, height);
  151.             DrawString('Transfer...');
  152.             MoveTo(menurect.right - CharWidth('T') - 15, height);
  153.             DrawChar(chr(17));
  154.             DrawChar('T');
  155.             
  156.             height := height + 16;
  157.             MoveTo(width, height);
  158.             DrawString('Edit Menu...');
  159.             
  160.             if thehandle^^.count = 0 then begin
  161.                 PenPat(QDglobals^.gray);
  162.                 PenMode(patBic);
  163.                 with menurect do
  164.                     SetRect(therect, left, top + 16, right, top + 32);
  165.                 PaintRect(therect);
  166.                 PenNormal;
  167.             end;
  168.             
  169.             height := height + 16;
  170.             MoveTo(menurect.left, menurect.top + 40);
  171.             Line(menurect.right - menurect.left, 0);
  172.             
  173.             for index := 1 to thehandle^^.count do begin
  174.                 height := height + 16;
  175.                 MoveTo(width, height);
  176.                 BlockMove(@thehandle^^.appl[index].name, @thestring, 32);
  177.                 DrawString(thestring);
  178.             end;
  179.             
  180.             HUnlock(Handle(thehandle));
  181.         
  182.         end;
  183.     
  184. (*******************************************************************
  185.     
  186.     menuchoose
  187.     ----------
  188.     
  189.     This routine is passed the mouse position, and sets the
  190.     “whichitem” parameter to the corresponding menu item.
  191.     
  192.     Since all the menu items are the same height, it's easy to
  193.     determine which one the mouse is in - provided it's somewhere
  194.     in the menu.  If it isn't, the routine should return zero in
  195.     the “whichitem” parameter.
  196.     
  197.     The routine should also return zero if the mouse is in the
  198.     dividing Line (item 3) or if it is in the “Edit Menu...” item
  199.     (item 2) and there are no applications to edit (it which case
  200.     the draw routine would have grayed out this item).
  201.     
  202.     Finally, if the mouse is in an active item, and that item is
  203.     different from the original value of “whichitem”, then the old
  204.     item should be un-highlighted, and the new one highlighted.
  205.     
  206. *******************************************************************)
  207.     
  208.     procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
  209.                     hitpoint : Point; var whichitem : integer);
  210.         
  211.         var
  212.             theitem            :    integer;
  213.             thehandle        :    thandle;
  214.             therect            :    Rect;
  215.         
  216.         begin
  217.             
  218.             if PtInRect(hitpoint, menurect) then
  219.                 theitem := 1 + ((hitpoint.v - menurect.top) div 16)
  220.             else
  221.                 theitem := 0;
  222.             
  223.             if theitem = 3 then
  224.                 theitem := 0
  225.             else if theitem = 2 then begin
  226.                 thehandle := thandle(GetResource('TRNS', 1001));
  227.                 if thehandle^^.count = 0 then
  228.                     theitem := 0;
  229.             end;
  230.             
  231.             if theitem <> whichitem then begin
  232.                 
  233.                 therect := menurect;
  234.                 therect.bottom := therect.top + 16 * theitem;
  235.                 therect.top := therect.bottom - 16;
  236.                 InvertRect(therect);
  237.                 
  238.                 if whichitem > 0 then begin
  239.                     OffsetRect(therect, 0, 16 * (whichitem - theitem));
  240.                     InvertRect(therect);
  241.                 end;
  242.                 
  243.                 whichitem := theitem;
  244.             
  245.             end;
  246.         
  247.         end;
  248.     
  249. (*******************************************************************
  250.     
  251.     menusize
  252.     --------
  253.     
  254.     This routine calculates the dimensions of the menu rectangle.
  255.     
  256.     The height is easy; the “TRNS” resource reveals the number of
  257.     applications listed on the menu; add the first three items and
  258.     multiply by 16.
  259.     
  260.     The width is found by walking the menu and finding the widest
  261.     item.  There are some adjustments for white space around the
  262.     individual items.
  263.     
  264.     A note:  Odd things happened in this routine, with the String
  265.     width changing as windows were opened.  I can't figure why this
  266.     occurred, since Inside Mac says the Menu Manager sets the port
  267.     to the Window Manager port.  Anyway, the TextFont, TextSize and
  268.     TextFace calls cleared up the problem.
  269.     
  270. *******************************************************************)
  271.     
  272.     procedure menusize(themenu : MenuHandle);
  273.         
  274.         var
  275.             savedload        :    logical;
  276.             thewidth            :    integer;
  277.             thehandle        :    thandle;
  278.             index                :    integer;
  279.             thestring        :    Str255;
  280.             newwidth            :    integer;
  281.         
  282.         begin
  283.             
  284.             savedload := logical(Ptr(resload)^);
  285.             SetResLoad(true);
  286.             
  287.             TextFont(systemFont);
  288.             TextSize(12);
  289.             TextFace([]);
  290.             
  291.             thewidth := StringWidth('Transfer...')
  292.                             + CharWidth('T') + 39;
  293.             newwidth := StringWidth('Edit Menu...') + 16;
  294.             if newwidth > thewidth then
  295.                 thewidth := newwidth;
  296.             
  297.             thehandle := thandle(GetResource('TRNS', 1001));
  298.             HLock(Handle(thehandle));
  299.             
  300.             for index := 1 to thehandle^^.count do begin
  301.                 BlockMove(@thehandle^^.appl[index].name, @thestring, 32);
  302.                 newwidth := StringWidth(thestring) + 16;
  303.                 if newwidth > thewidth then
  304.                     thewidth := newwidth;
  305.             end;
  306.             
  307.             HUnlock(Handle(thehandle));
  308.                 
  309.             themenu^^.menuHeight := 48 + 16 * thehandle^^.count;
  310.             themenu^^.menuWidth := thewidth;
  311.             
  312.             SetResLoad(savedload);
  313.         
  314.         end;
  315.     
  316. (******************************************************************)
  317.     
  318. end.
  319.     
  320. (******************************************************************)
  321.